package com.example.base_model.utils

/**
 * @Author jiangKunKun
 * @CreateDate 2025/7/4
 * @Description 可选值封装，替代 T?，支持函数式操作如 map、flatMap、filter、getOrElse 等。
 *               更加类型安全，避免 null 操作歧义。
 * @SpittingGrooves 不建议频繁使用，避免性能问题。多层嵌套使用
 * 具体使用
 * if else
 *      1. 逻辑简单直观
 *      2. 需要明确区分两种状态（null / 非 null）
 *      3. 对性能敏感
 *      4. 团队成员不熟悉函数式编程
 * let, run, takeIf, also, apply等
 *      这些操作符本身不会处理 null 的情况（除了 Elvis），你需要配合 ?: 使用
 *      1. 只关心非空值的情况
 *      2. 想用函数式风格简化代码
 *      3. 配合链式调用
 *      4. 需要临时作用域或上下文（如 run, apply）
 * Optional
 *      1. 多层嵌套空值处理
 *      2. 需要链式操作（map/flatMap/filter）
 *      3. 希望统一接口风格 / 与 Java 交互频繁（如返回 Optional）/ 构建 DSL 或通用库时
 * EmptyExt的onNull
 *      1. 只想在值为 null 时执行一段副作用（如打印日志、弹窗提示）
 *      2. 不想改变原有流程结构
 *      3. 作为辅助工具函数补充 let/takeIf 等
 */

/**
 * 表示一个可选值（可能存在也可能不存在）
 *
 * 使用方式：
 * val user: User? = findUser()
 * val optionalUser = user.asOptional() // 转换为 Optional<User>
 */
sealed class Optional<out T>

/**
 * 表示空值状态（类似 None）
 *
 * 示例：
 * val empty: Optional<Int> = Empty
 */
object Empty : Optional<Nothing>()

/**
 * 表示有值状态（类似 Some）
 *  在函数式编程中，“Present”表示“值存在”的状态
 * 示例：
 * val present: Optional<String> = Present("Hello")
 */
data class Present<out T>(val value: T) : Optional<T>()

/**
 * 将可空类型 T? 转换为 Optional<T>
 *
 * 示例：
 * val optionalName = name.asOptional()
 * optionalName.map { it.length }
 */
fun <T> T?.asOptional(): Optional<T> = if (this == null) Empty else Present(this)

/**
 * 对存在的值进行转换
 *
 * 如果当前为 Present，则应用转换函数并返回新的 Present；
 * 如果为空（Empty），则保持不变。
 *
 * 示例：
 * val userId: Optional<Int> = user.asOptional().map { it.id }
 * - 如果 user 存在 → 返回 Present(id)
 * - 否则 → 返回 Empty
 */
fun <T, R> Optional<T>.map(transform: (T) -> R): Optional<R> = when (this) {
    is Empty -> this
    is Present -> Present(transform(value))
}

/**
 * 链式变换生成另一个 Optional
 *
 * 与 map 类似，但允许返回一个新的 Optional。
 *
 * 示例：
 * val userEmail: Optional<String> = user.asOptional().flatMap {
 *     it.email.asOptional()
 * }
 * - 如果 user 存在且 email 存在 → Present(email)
 * - 否则 → Empty
 */
fun <T, R> Optional<T>.flatMap(transform: (T) -> Optional<R>): Optional<R> = when (this) {
    is Empty -> this
    is Present -> transform(value)
}

/**
 * 保留满足条件的值，否则转为 Empty
 *
 * 示例：
 * val validUser = user.asOptional().filter { it.id > 0 }
 * - 如果 id > 0 → 返回 Present(user)
 * - 否则 → Empty
 */
fun <T> Optional<T>.filter(predicate: (T) -> Boolean): Optional<T> = when (this) {
    is Empty -> this
    is Present -> if (predicate(value)) this else Empty
}

/**
 * 获取值或返回默认值
 *
 * 示例：
 * val name = user.asOptional().map { it.name }.getOrElse { "匿名用户" }
 * - 如果 name 存在 → 返回它
 * - 否则 → 返回 "匿名用户"
 */
fun <T> Optional<T>.getOrElse(default: () -> T): T = when (this) {
    is Empty -> default()
    is Present -> value
}

/**
 * 当前为空时，返回另一个 Optional
 *
 * 示例：
 * val result = user.asOptional().orElse { fetchDefaultUser().asOptional() }
 * - 如果原始用户为空 → 尝试获取默认用户
 * - 否则 → 返回原始用户
 */
fun <T> Optional<T>.orElse(option: () -> Optional<T>): Optional<T> = when (this) {
    is Empty -> option()
    else -> this
}

/**
 * 根据是否有值执行不同逻辑（类似模式匹配）
 *
 * 示例：
 * user.asOptional().fold(
 *     ifSome = { println("找到用户: ${it.name}") }
 *     ifEmpty = { println("用户不存在") },
 * )
 */
fun <T, R> Optional<T>.fold(ifEmpty: () -> R, ifSome: (T) -> R): R = when (this) {
    is Present -> ifSome(value)
    is Empty -> ifEmpty()
}

/**
 * 将 Optional<T> 转换为可空类型 T?
 *
 * 示例：
 * val nullableUser: User? = user.asOptional().toNullable()
 * 主要是给java使用
 */
fun <T> Optional<T>.toNullable(): T? = when (this) {
    is Present -> value
    is Empty -> null
}
